package kit

import (
	"fmt"
	pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/golang/protobuf/protoc-gen-go/generator"
	"strings"
)

type consul struct {
	consulName string
	consulapiName string
	stringsName string
}
const (
	consulPATH = "github.com/go-kit/kit/sd/consul"
	consulapiPATH = "github.com/hashicorp/consul/api"
	stringsPATH="strings"
	strconvPATH = "strconv"
)
func (c *consul) Name() string{
	return "consul"
}

func (c *consul) AddImport(g *grpc){
	c.consulName = string(g.gen.AddImport(consulPATH))
	c.consulapiName = string(g.gen.AddImport(consulapiPATH))
	c.stringsName = string(g.gen.AddImport(stringsPATH))
	g.gen.AddImport(strconvPATH)
}

func (c *consul) GeneratorRegistClient(g *grpc,file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int){
	origServName := service.GetName()
	fullServName := origServName
	if pkg := file.GetPackage(); pkg != "" {
		fullServName = pkg + "." + fullServName
	}
	servName := generator.CamelCase(origServName)


	g.P(fmt.Sprintf(`func NewBalance%sClient(registry string, server string, l log.Logger,maxtry int,timeout time.Duration) *balance%s {
	cfg :=%s.DefaultConfig()
	cfg.Address = registry
	cc,_ := %s.NewClient(cfg)
	c := %s.NewClient(cc)
	inst := %s.NewInstancer(c,l,server,[]string{},true)`,
		servName,servName,c.consulapiName,c.consulapiName,c.consulName,c.consulName,
	))

}

func ReplaceMulti(src string,oldAndNew...string)  string{
	for i:=0;i<len(oldAndNew);i+=2{
		src = strings.ReplaceAll(src,oldAndNew[i],oldAndNew[i+1])
	}
	return src
}

func (c *consul) GeneratorRegistServer(g *grpc,file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int){
	origServName := service.GetName()
	fullServName := origServName
	if pkg := file.GetPackage(); pkg != "" {
		fullServName = pkg + "." + fullServName
	}
	servName := generator.CamelCase(origServName)



	g.P(ReplaceMulti(`func Run{{svr}}Server(registry []string, serverName string, bind string, svraddr string,server {{svr}}Server, l log.Logger,healthcheckInterval string,deregisterCriticalServiceAfter string)  {	
	for _,v:=range registry {
		cfg := {{api}}.DefaultConfig()
		cfg.Address = v
		cc, e := {{api}}.NewClient(cfg)
		if e != nil {
			fmt.Println(e)
		}
		ipandport := strings.Split(svraddr, ":")
		porti, _ := strconv.Atoi(ipandport[1])
		c := {{consul}}.NewClient(cc)

		sv := &{{api}}.AgentServiceRegistration{
			ID:      fmt.Sprintf("%s-%s-%s", serverName, ipandport[0], ipandport[1]),
			Name:    serverName,
			Tags:    []string{},
			Port:    porti,
			Address: ipandport[0],
			Check: &{{api}}.AgentServiceCheck{
				Interval: healthcheckInterval,
				TCP: fmt.Sprintf("%s:%s", ipandport[0], ipandport[1]),
				DeregisterCriticalServiceAfter: deregisterCriticalServiceAfter,
			},
		}
		reg := {{consul}}.NewRegistrar(c, sv, l)
		reg.Register()
	}`,"{{svr}}",servName,"{{api}}",c.consulapiName,"{{consul}}",c.consulName))

}

// Init is called once after data structures are built but before
// code generation begins.
//func (z *zk) Init(g *generator.Generator){
//
//}
//// Generate produces the code generated by the plugin for this file,
//// except for the imports, by calling the generator's methods P, In, and Out.
//func (z *zk) Generate(file *FileDescriptor){
//
//}
//// GenerateImports produces the import declarations for this file.
//// It is called after Generate.
//func (z *zk) GenerateImports(file *FileDescriptor){
//
//}